//  -----------------------------------------------------------------------------------------------//
//   This file is part of SvnExternalUpdater                                                               //
//   Copyright (C)2008 Romain Verdier ( romain@codingly.com )                                      //
//                                                                                                 //
//   This program is free software; you can redistribute it and/or modify it under the terms       //
//   of the GNU General Public License as published by the Free Software Foundation; either        //
//   version 2 of the License, or (at your option) any later version. This program is distributed  //
//   in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied        //
//   warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public  //
//   License for more details.                                                                     //
//                                                                                                 //
//   You should have received a copy of the GNU General Public License along with this program; if //
//   not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. or  //
//   see http://www.fsf.org/licensing/licenses/gpl.html                                            //
//  -----------------------------------------------------------------------------------------------//
using System;
using System.Drawing;
using System.Threading;
using System.Windows.Forms;
using Codingly.SvnExternalUpdater.Layout;
using Codingly.SvnExternalUpdater.Presenters;
using Codingly.SvnExternalUpdater.Properties;
using Codingly.SvnExternalUpdater.Services;
using Ninject;

namespace Codingly.SvnExternalUpdater.Views
{
    public partial class MainView : Form, IMainView
    {
        private readonly LayoutManager layoutManager;
        private readonly SynchronizationContext syncContext;

        private bool exit;
        private bool externalsAreUpToDate;
        private bool mouseDown;
        private bool mouseDownResize;
        private Point mousePos;
        private string placeHolderKey;
        private MainPresenter presenter;
        private bool projectsAreUpToDate;
        private UserConfiguration userConfiguration;
        private IUserConfigurationService userConfigurationService;

        public MainView(IKernel kernel, LayoutManager layoutManager, IUserConfigurationService userConfigurationService)
        {
            InitializeComponent();
            kernel.Load(new WinformModule());
            this.syncContext = SynchronizationContext.Current;
            this.layoutManager = layoutManager;

            this.userConfigurationService = userConfigurationService;
            userConfiguration = userConfigurationService.GetConfiguration();
        }

        public void ClearViews()
        {
            this.panelProjects.Controls.Clear();
        }

        private void UpdateStatus()
        {
            this.syncContext.Post(delegate
                                      {
                                          if (this.projectsAreUpToDate)
                                          {
                                              this.pictureBoxMinus.Image = Resources.MinusGreen;
                                              this.pictureBoxResize.Image = Resources.ResizeGreen;
                                              this.pictureBoxRefresh.Image = Resources.RefreshGreen;
                                              this.notifyIcon.Icon = this.externalsAreUpToDate ? Resources.UdpateOkExternalOk : Resources.UpdateOkExternalNotOk;
                                          }
                                          else
                                          {
                                              this.pictureBoxMinus.Image = Resources.MinusRed;
                                              this.pictureBoxResize.Image = Resources.ResizeRed;
                                              this.pictureBoxRefresh.Image = Resources.RefreshRed;
                                              this.notifyIcon.Icon = this.externalsAreUpToDate ? Resources.UpdateNotOkExternalOk : Resources.UpdateNotOkExternalNotOk;
                                          }
                                          this.pictureBoxIcon.Image = this.notifyIcon.Icon.ToBitmap();
                                      }, null);
        }

        private void UpdateWelcomePanel()
        {
            this.panelWelcome.Visible = this.panelProjects.Controls.Count == 0;
        }

        private void linkLabelConfigure_Click(object sender, EventArgs e)
        {
            this.presenter.ConfigureMonitoredProjects();
        }

        private void linkLabelConfigure_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            this.presenter.ConfigureMonitoredProjects();
        }

        private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            userConfiguration.MainWindowSize = ClientSize;
            userConfiguration.MainWindowLocation = Location;
            userConfigurationService.Save(userConfiguration);

            switch (e.CloseReason)
            {
                case CloseReason.WindowsShutDown:
                case CloseReason.TaskManagerClosing:
                case CloseReason.FormOwnerClosing:
                case CloseReason.ApplicationExitCall:
                    break;
                case CloseReason.None:
                case CloseReason.MdiFormClosing:
                case CloseReason.UserClosing:
                    e.Cancel = !this.exit;
                    Hide();
                    break;
            }
        }

        private void MainForm_FormLoad(object sender, EventArgs e)
        {
            // restore location and size of the form on the desktop
            this.ClientSize = userConfiguration.MainWindowSize;
            this.Location = userConfiguration.MainWindowLocation;

        }

        private void MainForm_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Escape)
                Close();
        }

        private void notifyIcon1_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            Cursor.Current = Cursors.WaitCursor;
            if (!Visible)
                Show();
            Activate();
            Cursor.Current = Cursors.Default;
        }

        private void panelHeader_MouseDown(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                this.mouseDown = true;
                this.mousePos = e.Location;
            }
        }

        private void panelHeader_MouseMove(object sender, MouseEventArgs e)
        {
            if (this.mouseDown)
            {
                var p = new Point(e.X - this.mousePos.X, e.Y - this.mousePos.Y);
                Location = PointToScreen(p);
            }
        }

        private void panelHeader_MouseUp(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
                this.mouseDown = false;
        }

        private void pictureBoxMinus_Click(object sender, EventArgs e)
        {
            Close();
        }

        private void pictureBoxClose_Click(object sender, EventArgs e)
        {
            Application.Exit();
        }

        private void pictureBoxRefresh_Click(object sender, EventArgs e)
        {
            this.presenter.Refresh();
        }

        private void pictureBoxResize_MouseDown(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                this.mouseDownResize = true;
                this.mousePos = e.Location;
            }
        }

        private void pictureBoxResize_MouseMove(object sender, MouseEventArgs e)
        {
            if (this.mouseDownResize)
                ClientSize = new Size(ClientSize.Width + e.X - this.mousePos.X, ClientSize.Height + e.Y - this.mousePos.Y);
        }

        private void pictureBoxResize_MouseUp(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
                this.mouseDownResize = false;
        }

        private void toolStripMenuItemAbout_Click(object sender, EventArgs e)
        {
            this.presenter.ShowAbout();
        }

        private void toolStripMenuItemExit_Click(object sender, EventArgs e)
        {
            this.presenter.Stop();
            this.exit = true;
            Close();
        }

        private void toolStripMenuItemMonitoredProjects_Click(object sender, EventArgs e)
        {
            this.presenter.ConfigureMonitoredProjects();
        }

        public MainPresenter Presenter
        {
            get { return this.presenter; }
            set { this.presenter = value; }
        }

        public bool ExternalsAreUpToDate
        {
            set
            {
                this.externalsAreUpToDate = value;
                UpdateStatus();
            }
        }

        public void Run()
        {
            Application.Run(this);
        }

        public void BeginUpdate()
        {
            this.syncContext.Post(delegate
                                      {
                                          this.layoutManager.SuspendLayout(this.placeHolderKey);
                                          this.panelWaiting.Visible = true;
                                      }, null);
        }

        public void EndUpdate()
        {
            this.syncContext.Post(delegate
                                      {
                                          this.panelWaiting.Visible = false;
                                          this.layoutManager.ResumeLayout(this.placeHolderKey);
                                          UpdateWelcomePanel();
                                      }, null);
        }

        public bool ProjectsAreUpToDate
        {
            set
            {
                this.projectsAreUpToDate = value;
                UpdateStatus();
            }
        }

        public string PlaceHolderKey
        {
            get { return this.placeHolderKey; }
            set
            {
                this.placeHolderKey = value;
                this.layoutManager.RegisterPlaceHolder(this.placeHolderKey, this);
            }
        }

        void IViewPlaceHolder.SuspendLayout()
        {
            this.panelProjects.SuspendLayout();
        }

        public void AppendView(object view)
        {
            var control = view as Control;
            if (control != null)
            {
                this.syncContext.Post(delegate
                                          {
                                              this.panelProjects.Controls.Add(control);
                                              control.Dock = DockStyle.Top;
                                          }, null);
            }
        }

        public void RemoveView(object view)
        {
            var control = view as Control;
            if (control != null)
            {
                this.syncContext.Post(delegate
                                          {
                                              if (this.panelProjects.Controls.Contains(control))
                                                  this.panelProjects.Controls.Remove(control);
                                          }, null);
            }
        }

        void IViewPlaceHolder.ResumeLayout()
        {
            this.panelProjects.ResumeLayout();
        }
    }
}